package chooongg.base.utils

import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.FloatRange
import androidx.annotation.IntRange
import java.util.*
import kotlin.math.*

object ColorUtils {

    /**
     * 颜色+透明度 组合
     */
    fun setAlphaComponent(
        @ColorInt color: Int,
        @IntRange(from = 0x0, to = 0xFF) alpha: Int
    ): Int {
        return (color and 0x00FFFFFF) or (alpha shl 24)
    }

    /**
     * 颜色+透明度 组合
     */
    fun setAlphaComponent(
        @ColorInt color: Int,
        @FloatRange(from = 0.0, to = 1.0) alpha: Float
    ): Int {
        return (color and 0x00FFFFFF) or ((alpha * 255.0f + 0.5f).toInt() shl 24)
    }

    /**
     * 颜色+红色 组合
     */
    fun setRedComponent(
        @ColorInt color: Int,
        @IntRange(from = 0x0, to = 0xFF) red: Int
    ): Int {
        return (color and 0xFF00FFFF.toInt()) or (red shl 16)
    }

    /**
     * 颜色+红色 组合
     */
    fun setRedComponent(
        @ColorInt color: Int,
        @FloatRange(from = 0.0, to = 1.0) red: Float
    ): Int {
        return (color and 0xFF00FFFF.toInt()) or ((red * 255.0f + 0.5f).toInt() shl 16)
    }

    /**
     * 颜色+绿色 组合
     */
    fun setGreenComponent(
        @ColorInt color: Int,
        @IntRange(from = 0x0, to = 0xFF) green: Int
    ): Int {
        return (color and 0xFFFF00FF.toInt()) or (green shl 8)
    }

    /**
     * 颜色+绿色 组合
     */
    fun setGreenComponent(
        @ColorInt color: Int,
        @FloatRange(from = 0.0, to = 1.0) green: Float
    ): Int {
        return (color and 0xFFFF00FF.toInt()) or ((green * 255.0f + 0.5f).toInt() shl 8)
    }

    /**
     * 颜色+蓝色 组合
     */
    fun setBlueComponent(
        @ColorInt color: Int,
        @IntRange(from = 0x0, to = 0xFF) blue: Int
    ): Int {
        return (color and 0xFFFFFF00.toInt()) or blue
    }

    /**
     * 颜色+蓝色 组合
     */
    fun setBlueComponent(
        @ColorInt color: Int,
        @FloatRange(from = 0.0, to = 1.0) blue: Float
    ): Int {
        return (color and 0xFFFFFF00.toInt()) or (blue * 255.0f + 0.5f).toInt()
    }

    /**
     * 字符串转颜色
     * @sample #RRGGBB
     * @sample #AARRGGBB
     */
    fun String.toColorInt() = Color.parseColor(this)

    /**
     * 颜色转RGB字符串
     */
    fun Int.toColorRGBString(): String? {
        var colorInt = this
        colorInt = colorInt and 0x00ffffff
        var color = Integer.toHexString(colorInt)
        while (color.length < 6) {
            color = "0$color"
        }
        return "#$color".toUpperCase(Locale.getDefault())
    }

    /**
     * 颜色转ARGB字符串
     */
    fun Int.toColorArgbString(): String? {
        var color = Integer.toHexString(this)
        while (color.length < 6) {
            color = "0$color"
        }
        while (color.length < 8) {
            color = "f$color"
        }
        return "#$color".toUpperCase(Locale.getDefault())
    }

    /**
     * 是否是深色
     */
    fun isColorDark(@ColorInt color: Int): Boolean {
        val darkness =
            1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255
        return darkness >= 0.5
    }

    /**
     * 根据比例，在两个color值之间计算出一个color值
     * **注意该方法是ARGB通道分开计算比例的**
     *
     * @param fromColor 开始的color值
     * @param toColor   最终的color值
     * @param fraction  比例，取值为[0,1]，为0时返回 fromColor， 为1时返回 toColor
     * @return 计算出的color值
     */
    fun computeColor(@ColorInt fromColor: Int, @ColorInt toColor: Int, fraction: Float): Int {
        var fractionTemp = fraction
        fractionTemp = max(min(fractionTemp, 1f), 0f)

        val minColorA = Color.alpha(fromColor)
        val maxColorA = Color.alpha(toColor)
        val resultA = ((maxColorA - minColorA) * fractionTemp).toInt() + minColorA

        val minColorR = Color.red(fromColor)
        val maxColorR = Color.red(toColor)
        val resultR = ((maxColorR - minColorR) * fractionTemp).toInt() + minColorR

        val minColorG = Color.green(fromColor)
        val maxColorG = Color.green(toColor)
        val resultG = ((maxColorG - minColorG) * fractionTemp).toInt() + minColorG

        val minColorB = Color.blue(fromColor)
        val maxColorB = Color.blue(toColor)
        val resultB = ((maxColorB - minColorB) * fractionTemp).toInt() + minColorB

        return Color.argb(resultA, resultR, resultG, resultB)
    }
}